package com.stottlerhenke.simbionic.common.parser;

import java.util.ArrayList;

import com.stottlerhenke.simbionic.api.SB_Exception;
import com.stottlerhenke.simbionic.common.SB_Logger;
import com.stottlerhenke.simbionic.common.SIM_Constants;
import com.stottlerhenke.simbionic.editor.SB_TypeManager;
import com.stottlerhenke.simbionic.editor.gui.SB_Polymorphism;
import com.stottlerhenke.simbionic.editor.parser.SB_ParserEditorInterface;

/**
 * This class provides the capability to parse C expressions containing
 * variables and function calls.
 */
public class SB_Parser 
{
  private SB_Lexer _lexer;
  private SB_ParserAppInterface _appInterface;
  private SB_Logger _logger;

  public SB_Parser(SB_ParserAppInterface iface,SB_Logger logger) 
	{
    _appInterface = iface;
    _lexer = new SB_Lexer();
    _logger = logger;
  }

  /**
   * Retrieves the lexer used by the parser.
   */
  private SB_Lexer Lexer() { return _lexer; }
  
  public void setTypeManager(SB_TypeManager typeManager){
	  if (_appInterface instanceof SB_ParserEditorInterface)
		  ((SB_ParserEditorInterface)_appInterface).setTypeManager(typeManager);
  }
  
  // allow the parser to parse variables
  public void setPoly(SB_Polymorphism poly) { 
	  if (_appInterface instanceof SB_ParserEditorInterface)
		  ((SB_ParserEditorInterface)_appInterface).setPoly(poly);
  }
	
  public SB_ExpressionNode Parse( String expr){ return Parse(expr, EParseFlags.kNoFlag);}
  
  public SB_ExpressionNode Parse( String expr,EParseFlags flags){
     //Lexer().SetTokenPrinting(true);
      
      _appInterface.SetCompleteExpression(expr);
      
     Lexer().Initialize(expr);
     
     if (SIM_Constants.DEBUG_INFO_ON && (_logger != null))
     		_logger.log(".Parsing expression '" + expr + "'",SB_Logger.INIT);

     SB_ExpressionNode exp = null;
     SB_ObjectRefWrapper expWrapper = new SB_ObjectRefWrapper(exp);
     try
     {
       if (ParseExpression(expWrapper,flags) == EParseResult.kNoMatch)
       {
          // always return some kind of error object instead of a bare null
          lexeme tmp = Lexer().GetCurrentToken();
          if (tmp.type == EToken.INVALID_T.getState())
             exp = _appInterface.CreateErrorNode(Lexer().GetCurrentToken().lex_str);
          else
             exp = _appInterface.CreateErrorNode("Could not parse expression '" + expr + "'");
        }else{
          exp = (SB_ExpressionNode)expWrapper.GetObjectRef();
          if (exp.IsValid()) {
            // make sure all input tokens have been used up
            if (Lexer().GetCurrentToken().type != EToken.EOF_T.getState()) {
              exp = _appInterface.CreateErrorNode(
                  "Garbage at end of expression: " +
                  Lexer().GetCurrentToken().lex_str + ".");
            }
          }
        }
      }
      catch (SB_ParseException exc)
      {
         // politely return an error
         exp = _appInterface.CreateErrorNode(exc.getMessage());
       }
      return exp;
  }


   private  EParseResult ParseExpression(SB_ObjectRefWrapper matchWrapper, EParseFlags flags)
   throws SB_ParseException
   {
        // check for any special-case expression types and parse them separately
        if ((flags.getState() & EParseFlags.kString.getState()) != 0)
        {
                return ParseString(matchWrapper);
        }

        // otherwise parse a normal expression
        if (ParseOr(matchWrapper,flags) == EParseResult.kMatch)
        {
                return ParseExpressionAux(matchWrapper,flags);
        }
        SB_ExpressionNode match = (SB_ExpressionNode)matchWrapper.GetObjectRef();
        return (match == null) ? EParseResult.kNoMatch : EParseResult.kBadExpression;
   }

   private EParseResult ParseString(SB_ObjectRefWrapper matchWrapper){
     SB_ExpressionNode match = null;
     String theString = new String( Lexer().GetInputString() );

    // check for illegal double quotes
    if (theString.matches("\"")){
      match = _appInterface.CreateErrorNode("Illegal double quote in string expression.");
      matchWrapper.SetObjectRef(match);
      return EParseResult.kBadExpression;
    }
    match = _appInterface.CreateConstantNode(theString);

    // advance the tokenizer to end of string
    while (Lexer().GetCurrentToken().type != EToken.EOF_T.getState()){
      Lexer().GetNextToken();
    }
    matchWrapper.SetObjectRef(match);
    return EParseResult.kMatch;
   }


   private EParseResult ParseExpressionAux(SB_ObjectRefWrapper matchWrapper, EParseFlags flags)
   throws SB_ParseException
   {
        SB_ExpressionNode match = (SB_ExpressionNode)matchWrapper.GetObjectRef();
        if (Lexer().IsToken(EToken.QUESTION_T.getState()))
        {
                SB_ExpressionNode arg2 = null;
                SB_ExpressionNode arg3 = null;
                SB_ObjectRefWrapper arg2Wrapper = new SB_ObjectRefWrapper(arg2);
                SB_ObjectRefWrapper arg3Wrapper = new SB_ObjectRefWrapper(arg3);
                
                if (ParseOr(arg2Wrapper,flags) == EParseResult.kNoMatch)
                {
                    arg2 = _appInterface.CreateErrorNode("Missing second argument to ?: operator.");
                }
                else if (Lexer().IsToken(EToken.COLON_T.getState()))
                {
                    arg2 = (SB_ExpressionNode)arg2Wrapper.GetObjectRef();
                    if (ParseOr(arg3Wrapper,flags) == EParseResult.kNoMatch)
                    {
                        arg3 = _appInterface.CreateErrorNode("Missing third argument to ?: operator.");
                    }
                    else
                        arg3 = (SB_ExpressionNode)arg3Wrapper.GetObjectRef();
                }
                else
                    arg2 = _appInterface.CreateErrorNode("Missing ':' in ?: operator.");
                    
                match = _appInterface.CreateTernaryOpNode( match, arg2, arg3, ETernaryOp.kTernaryOp );
                matchWrapper.SetObjectRef(match);
                return ParseExpressionAux(matchWrapper,flags);
        }
        else
        {
                return EParseResult.kMatch;	// EMPTY PRODUCTION
        }
   }

   private  EParseResult ParseOr(SB_ObjectRefWrapper matchWrapper, EParseFlags flags)
   throws SB_ParseException
   {
        if (ParseAnd(matchWrapper,flags) == EParseResult.kMatch)
        {
            return ParseOrAux(matchWrapper,flags);
        }
        SB_ExpressionNode match = (SB_ExpressionNode)matchWrapper.GetObjectRef();
        return (match == null) ? EParseResult.kNoMatch : EParseResult.kBadExpression;
   }

   private EParseResult ParseOrAux(SB_ObjectRefWrapper matchWrapper, EParseFlags flags)
   throws SB_ParseException
   {
        SB_ExpressionNode match = (SB_ExpressionNode)matchWrapper.GetObjectRef();
        if (Lexer().IsToken(EToken.OR_T.getState()))
        {
                SB_ExpressionNode arg2 = null;
                SB_ObjectRefWrapper arg2Wrapper = new SB_ObjectRefWrapper(arg2);
                if (ParseAnd(arg2Wrapper,flags) == EParseResult.kNoMatch)
                {
                        arg2 = _appInterface.CreateErrorNode("Missing right-hand argument to || operator.");
                }
                arg2 = (SB_ExpressionNode)arg2Wrapper.GetObjectRef();
                match = _appInterface.CreateBinaryOpNode( match, arg2, EBinaryOp.kOrOp );
                matchWrapper.SetObjectRef(match);
                return ParseOrAux(matchWrapper,flags);
        }
        else
        {
                return EParseResult.kMatch; // EMPTY PRODUCTION
        }
   }

   private EParseResult ParseAnd(SB_ObjectRefWrapper matchWrapper, EParseFlags flags)
   throws SB_ParseException
   {
        if (ParseRelational(matchWrapper,flags) == EParseResult.kMatch)
        {
                if (ParseAndAux(matchWrapper,flags) == EParseResult.kMatch)
                {
                        return EParseResult.kMatch;
                }
        }
        SB_ExpressionNode match = (SB_ExpressionNode)matchWrapper.GetObjectRef();
        return (match == null) ? EParseResult.kNoMatch : EParseResult.kBadExpression;
    }


    private EParseResult ParseAndAux(SB_ObjectRefWrapper matchWrapper, EParseFlags flags)
    throws SB_ParseException
    {
        //FATAL( (match != null), "Error in ParseAndAux" );
        SB_ExpressionNode match = (SB_ExpressionNode)matchWrapper.GetObjectRef();
        if (Lexer().IsToken(EToken.AND_T.getState()))
        {
                SB_ExpressionNode arg2 = null;
                SB_ObjectRefWrapper arg2Wrapper = new SB_ObjectRefWrapper(arg2);
                if (ParseRelational(arg2Wrapper,flags) == EParseResult.kNoMatch)
                {
                        arg2 = _appInterface.CreateErrorNode("Missing right-hand argument to && operator.");
                }
                arg2 = (SB_ExpressionNode)arg2Wrapper.GetObjectRef();
                match = _appInterface.CreateBinaryOpNode( match, arg2, EBinaryOp.kAndOp );
                matchWrapper.SetObjectRef(match);
                return ParseAndAux(matchWrapper,flags);
        }
        else
        {
                return EParseResult.kMatch;	// EMPTY PRODUCTION
        }
     }


     private EParseResult ParseRelational(SB_ObjectRefWrapper matchWrapper, EParseFlags flags)
     throws SB_ParseException
     {
        //FATAL( (match == null), "Error in ParseRelational" );

        if (ParseAddition(matchWrapper,flags) == EParseResult.kMatch)
        {
                if (ParseRelationalAux(matchWrapper,flags) == EParseResult.kMatch)
                {
                        return EParseResult.kMatch;
                }
        }
        SB_ExpressionNode match = (SB_ExpressionNode)matchWrapper.GetObjectRef();
        return (match == null) ? EParseResult.kNoMatch : EParseResult.kBadExpression;
      }


      private EParseResult ParseRelationalAux(SB_ObjectRefWrapper matchWrapper, EParseFlags flags)
      throws SB_ParseException
      {
        //FATAL( (match != null), "Error in ParseRelationalAux" );
        SB_ExpressionNode match = (SB_ExpressionNode)matchWrapper.GetObjectRef();
        if (Lexer().IsToken(EToken.RELOP_T.getState(), SB_Lexer.ANY_SUBTYPE))
        {
                // found relational operator -- extract the subtype
                EBinaryOp op = MapBinaryOperator( Lexer().GetPreviousToken() );

                SB_ExpressionNode arg2 = null;
                SB_ObjectRefWrapper arg2Wrapper = new SB_ObjectRefWrapper(arg2);
                if (ParseAddition(arg2Wrapper,flags) == EParseResult.kNoMatch)
                {
                        arg2 = _appInterface.CreateErrorNode("Missing right-hand argument to " + BinaryOpToString(op) + "operator");
                }else{
                  arg2 = (SB_ExpressionNode)arg2Wrapper.GetObjectRef();
                }

                match = _appInterface.CreateBinaryOpNode( match, arg2, op );
                matchWrapper.SetObjectRef(match);
                return ParseRelationalAux(matchWrapper,flags);
        }
        else
        {
                return EParseResult.kMatch;	// EMPTY PRODUCTION
        }
      }



      private EParseResult ParseAddition(SB_ObjectRefWrapper matchWrapper, EParseFlags flags)
      throws SB_ParseException
      {
        //FATAL( (match == null), "Error in ParseAddition" );
        if (ParseMultiplication(matchWrapper,flags) == EParseResult.kMatch)
        {
                if (ParseAdditionAux(matchWrapper,flags) == EParseResult.kMatch)
                {
                        return EParseResult.kMatch;
                }
        }
        SB_ExpressionNode match = (SB_ExpressionNode)matchWrapper.GetObjectRef();
        return (match == null) ? EParseResult.kNoMatch : EParseResult.kBadExpression;
      }


      private EParseResult ParseAdditionAux(SB_ObjectRefWrapper matchWrapper, EParseFlags flags)
      throws SB_ParseException
      {
        //FATAL( (match != null), "Error in ParseAdditionAux" );
        SB_ExpressionNode match = (SB_ExpressionNode)matchWrapper.GetObjectRef();
        if (Lexer().IsToken(EToken.ADDOP_T.getState(), SB_Lexer.ANY_SUBTYPE))
        {
                // found addition operator -- extract the subtype
                EBinaryOp op = MapBinaryOperator( Lexer().GetPreviousToken() );

                SB_ExpressionNode arg2 = null;
                SB_ObjectRefWrapper arg2Wrapper = new SB_ObjectRefWrapper(arg2);
                if (ParseMultiplication(arg2Wrapper,flags) == EParseResult.kNoMatch)
                {
                        arg2 = _appInterface.CreateErrorNode("Missing right-hand argument to " + BinaryOpToString(op) + " operator.");
                }else{
                  arg2 = (SB_ExpressionNode)arg2Wrapper.GetObjectRef();
                }
                match = _appInterface.CreateBinaryOpNode( match, arg2, op );
                matchWrapper.SetObjectRef(match);

                return ParseAdditionAux(matchWrapper,flags);
        }
        else
        {
                return EParseResult.kMatch;	// EMPTY PRODUCTION
        }
      }


      private EParseResult ParseMultiplication(SB_ObjectRefWrapper matchWrapper, EParseFlags flags)
      throws SB_ParseException
      {
        //FATAL( (match == null), "Error in ParseMultiplication" );
        if (ParseMemberAccess(matchWrapper,flags) == EParseResult.kMatch)
        {
                if (ParseMultiplicationAux(matchWrapper,flags) == EParseResult.kMatch)
                {
                        return EParseResult.kMatch;
                }
        }
        SB_ExpressionNode match = (SB_ExpressionNode)matchWrapper.GetObjectRef();
        return (match == null) ? EParseResult.kNoMatch : EParseResult.kBadExpression;
      }


      private EParseResult ParseMultiplicationAux(SB_ObjectRefWrapper matchWrapper, EParseFlags flags)
      throws SB_ParseException
      {
        //FATAL( (match != null), "Error in ParseMultiplicationAux" );
        SB_ExpressionNode match = (SB_ExpressionNode)matchWrapper.GetObjectRef();
        if (Lexer().IsToken(EToken.MULOP_T.getState(), SB_Lexer.ANY_SUBTYPE))
        {
                // found multiplicative operator -- extract the subtype
                EBinaryOp op = MapBinaryOperator( Lexer().GetPreviousToken() );

                SB_ExpressionNode arg2 = null;
                SB_ObjectRefWrapper arg2Wrapper = new SB_ObjectRefWrapper(arg2);
                if (ParseMemberAccess(arg2Wrapper,flags) == EParseResult.kNoMatch)
                {
                  arg2 = _appInterface.CreateErrorNode("Missing right-hand argument to " + BinaryOpToString(op) + " operator.");
                }else{
                  arg2 = (SB_ExpressionNode)arg2Wrapper.GetObjectRef();
                }
                match = _appInterface.CreateBinaryOpNode( match, arg2, op );
                matchWrapper.SetObjectRef(match);
                return ParseMultiplicationAux(matchWrapper,flags);
        }
        else
        {
                return EParseResult.kMatch;	// EMPTY PRODUCTION
        }
     }

     private EParseResult ParseMemberAccess(SB_ObjectRefWrapper matchWrapper, EParseFlags flags)
     throws SB_ParseException
     {
        //FATAL( (match == null), "Error in ParseMemberAccess" );
        if (ParseUnary(matchWrapper,flags) == EParseResult.kMatch)
        {
                if (ParseMemberAccessAux(matchWrapper,flags) == EParseResult.kMatch)
                {
                        return EParseResult.kMatch;
                }
        }
        SB_ExpressionNode match = (SB_ExpressionNode)matchWrapper.GetObjectRef();
        return (match == null) ? EParseResult.kNoMatch : EParseResult.kBadExpression;
      }


      private EParseResult ParseMemberAccessAux(SB_ObjectRefWrapper matchWrapper, EParseFlags flags)
      	throws SB_ParseException
      {
        //FATAL( (match != null), "Error in ParseMemberAccessAux" );
        SB_ExpressionNode match = (SB_ExpressionNode)matchWrapper.GetObjectRef();
        if (Lexer().IsToken(EToken.DOT_T.getState()))
        {
                // found struct member-access operator
                EBinaryOp op = MapBinaryOperator( Lexer().GetPreviousToken() );

                // second argument must be a simple "string" token that names the member
                SB_ExpressionNode arg2 = null;
                if( EParseResult.kNoMatch != ParseFunction(matchWrapper, flags, true))
                {
                				arg2 = (SB_ExpressionNode) matchWrapper.GetObjectRef();
                }
                else
                if (Lexer().IsToken(EToken.IDENT_T.getState()))
                {
                        arg2 = _appInterface.CreateConstantNode( Lexer().GetPreviousToken().lex_str, true );
                }
                else
                {
                        arg2 = _appInterface.CreateErrorNode("Missing right-hand argument to . operator.");
                }

                match = _appInterface.CreateBinaryOpNode( match, arg2, op );
                matchWrapper.SetObjectRef(match);
                return ParseMemberAccessAux(matchWrapper,flags);
        }
        else
        {
                return EParseResult.kMatch;	// EMPTY PRODUCTION
        }
      }

    private EParseResult ParseUnary(SB_ObjectRefWrapper matchWrapper, EParseFlags flags)
    throws SB_ParseException
    {
        //FATAL( (match == null), "Error in ParseUnary" );
        SB_ExpressionNode match = null;
        if (Lexer().IsToken(EToken.BANG_T.getState()) || Lexer().IsToken(EToken.ADDOP_T.getState(), EAddop.SUB.getState()))
        {
                // found unary operator, determine subtype
                EUnaryOp op = MapUnaryOperator( Lexer().GetPreviousToken() );

                SB_ExpressionNode arg = null;
                SB_ObjectRefWrapper argWrapper = new SB_ObjectRefWrapper(arg);
                if (ParseUnary(argWrapper,flags) == EParseResult.kNoMatch)
                {
                        arg = _appInterface.CreateErrorNode("Missing argument to unary " + UnaryOpToString(op) + " operator.");
                }else{
                  arg = (SB_ExpressionNode)argWrapper.GetObjectRef();
                }
                match = _appInterface.CreateUnaryOpNode( arg, op );
                matchWrapper.SetObjectRef(match);
                return EParseResult.kMatch;
        }
    	else if (Lexer().IsToken(EToken.PAREN_T.getState(), EParen.OPEN.getState()))
    	{
    		// check for the unary typecasting operator
    		if (Lexer().IsToken(EToken.IDENT_T.getState()))
    		{
    			// check for the special typecasting keywords 
    			if (Lexer().GetPreviousToken().lex_str.equals("float") ||
    				Lexer().GetPreviousToken().lex_str.equals("int") ||
    				Lexer().GetPreviousToken().lex_str.equals("double") ||
    				Lexer().GetPreviousToken().lex_str.equals("short") ||
    				Lexer().GetPreviousToken().lex_str.equals("long") ||
    				Lexer().GetPreviousToken().lex_str.equals("byte"))
    			{
    			    EUnaryOp op = EUnaryOp.kCastIntOp;
    			    
    			    switch (Lexer().GetPreviousToken().lex_str.charAt(0))
    			    {
    			    case 'f' : op = EUnaryOp.kCastFloatOp; break;
    			    case 'i' : op = EUnaryOp.kCastIntOp; break;
    			    case 'd' : op = EUnaryOp.kCastDoubleOp; break;
    			    case 's' : op = EUnaryOp.kCastShortOp; break;
    			    case 'b' : op = EUnaryOp.kCastByteOp; break;
    			    case 'l' : op = EUnaryOp.kCastLongOp; break;
    			    }

    				if (Lexer().IsToken(EToken.PAREN_T.getState(),EParen.CLOSE.getState()))
    				{
    					SB_ExpressionNode arg = null;
    					if (ParseExpression(matchWrapper,flags) == EParseResult.kNoMatch)
    					{
    						arg = _appInterface.CreateErrorNode("Malformed typecasting operator.");
    						matchWrapper.SetObjectRef(arg);
    						return EParseResult.kMatch;
    					}

    					match = _appInterface.CreateUnaryOpNode( (SB_ExpressionNode)matchWrapper.GetObjectRef(), op );
    					matchWrapper.SetObjectRef(match);
    					return EParseResult.kMatch;
    				}
    			}
    			try {
    				Lexer().PushbackToken();
    			} catch (SB_Exception e) { throw new SB_ParseException(e.getMessage(),0); }
    		}
    		try {
    			Lexer().PushbackToken();
    		} catch (SB_Exception e) { throw new SB_ParseException(e.getMessage(),0); }
    	}

    	// no unary operator, so keep parsing
        return ParseParentheses(matchWrapper,flags);
      }


      private EParseResult ParseParentheses(SB_ObjectRefWrapper matchWrapper, EParseFlags flags)
      throws SB_ParseException
      {
        //FATAL( (match == null), "Error in ParseParentheses" );
        SB_ExpressionNode match = null;
        if (Lexer().IsToken(EToken.PAREN_T.getState(), EParen.OPEN.getState()))
        {
                if (ParseExpression(matchWrapper,flags) == EParseResult.kMatch)
                {
                        match = (SB_ExpressionNode) matchWrapper.GetObjectRef();
                        if (Lexer().IsToken(EToken.PAREN_T.getState(), EParen.CLOSE.getState()))
                        {
                                match = _appInterface.CreateUnaryOpNode( match, EUnaryOp.kParenOp );
                                matchWrapper.SetObjectRef(match);
                                return EParseResult.kMatch;
                        }
                        else
                        {
                                match = _appInterface.CreateErrorNode("Missing closing parenthesis, found " + Lexer().GetCurrentToken().lex_str + " instead.");
                                matchWrapper.SetObjectRef(match);
                                return EParseResult.kBadExpression;
                        }
                }
                else if (match == null)
                {
                        match = _appInterface.CreateErrorNode("Empty parenthetical expression.");
                        matchWrapper.SetObjectRef(match);
                        return EParseResult.kBadExpression;
                }
        }
        else
        {
                return ParseTerm(matchWrapper,flags);
        }
        return (match == null) ? EParseResult.kNoMatch : EParseResult.kBadExpression;
      }


      private EParseResult ParseTerm(SB_ObjectRefWrapper matchWrapper, EParseFlags flags)
      throws SB_ParseException
      {
        //FATAL( (match == null), "Error in ParseTerm" );
        SB_ExpressionNode match = null;
        EParseResult result = ParseFunction(matchWrapper,flags);

        if (((flags.getState() & EParseFlags.kNoFunctions.getState()) != 0) && (result == EParseResult.kMatch))
        {
            // parsing a special expression without function calls
            match = _appInterface.CreateErrorNode("No function calls allowed in expression.");
            matchWrapper.SetObjectRef(match);
            return EParseResult.kBadExpression;
        }

        if (result != EParseResult.kNoMatch)
        {
            return result;
        }
        else if (ParseVector(matchWrapper) == EParseResult.kMatch)
        {
            // vector constant
            return EParseResult.kMatch;
        }
        else if(ParseArray(matchWrapper) == EParseResult.kMatch)
        {
        	//Array constant
        	return EParseResult.kMatch;
        }
        else if (Lexer().IsToken(EToken.IDENT_T.getState()))
        {
            // looks like an identifier

            // check for the special boolean keywords "true
            if (Lexer().GetPreviousToken().lex_str.equals("true") )
            {
                match = _appInterface.CreateConstantNode(true);
                matchWrapper.SetObjectRef(match);
                return EParseResult.kMatch;
            }
            else if (Lexer().GetPreviousToken().lex_str.equals("false"))
            {
                match = _appInterface.CreateConstantNode(false);
                matchWrapper.SetObjectRef(match);
                return EParseResult.kMatch;
            }
            else if ((match = _appInterface.CreateClassNode(Lexer().GetPreviousToken().lex_str)) != null)
            {
            	// found a class name, part of a static reference
            	matchWrapper.SetObjectRef(match);
            	return EParseResult.kMatch;
            }

            if ((flags.getState() & EParseFlags.kNoVariables.getState()) != 0)
            {
                // parsing a special expression without variables
                match = _appInterface.CreateErrorNode("No variables allowed in expression.");
                matchWrapper.SetObjectRef(match);
                return EParseResult.kBadExpression;
            }

            match = _appInterface.CreateVariableNode(Lexer().GetPreviousToken().lex_str);
            matchWrapper.SetObjectRef(match);
            return EParseResult.kMatch;
        }
        else if (Lexer().IsToken(EToken.INTCON_T.getState()))
        {
            // integer constant

            int value = Integer.parseInt( Lexer().GetPreviousToken().lex_str );
            match = _appInterface.CreateConstantNode( value );
            matchWrapper.SetObjectRef(match);
            return EParseResult.kMatch;
        }
        else if (Lexer().IsToken(EToken.REALCON_T.getState()))
        {
            // floating point constant

            float value = Float.parseFloat( Lexer().GetPreviousToken().lex_str );
            match = _appInterface.CreateConstantNode( value );
            matchWrapper.SetObjectRef(match);
            return EParseResult.kMatch;
        }
        else if (Lexer().IsToken(EToken.STRCON_T.getState()))
        {
            // string constant

            match = _appInterface.CreateConstantNode( Lexer().GetPreviousToken().lex_str );
            matchWrapper.SetObjectRef(match);
            return EParseResult.kMatch;
        }

        return (match == null) ? EParseResult.kNoMatch : EParseResult.kBadExpression;
    }

    private EParseResult ParseFunction(SB_ObjectRefWrapper matchWrapper, EParseFlags flags)
    throws SB_ParseException
		{
    	return ParseFunction(matchWrapper, flags, false);
		}
			
    /**
     * 
     * @param isMethod false if this is a normal functin, true if this is a member function
     */
    private EParseResult ParseFunction(SB_ObjectRefWrapper matchWrapper, EParseFlags flags, boolean isMethod)
    throws SB_ParseException
    {
        //FATAL( (match == null), "Error in ParseFunction" );
        SB_ExpressionNode match = null;
        if (Lexer().IsToken(EToken.IDENT_T.getState()))
        {
                // found the function name
                String funcName = new String( Lexer().GetPreviousToken().lex_str );

                if (Lexer().IsToken(EToken.PAREN_T.getState(), EParen.OPEN.getState()))
                {
        				if( !isMethod )
        					match = _appInterface.CreateFunctionNode(funcName);
        				else
        					match = _appInterface.CreateMethodNode((SB_ExpressionNode) matchWrapper.GetObjectRef(), funcName);
                	
                        matchWrapper.SetObjectRef(match);
                        if (!match.IsValid())
                        {
                                // not a known function name

                                return EParseResult.kBadExpression;
                        }

                        if (Lexer().IsToken(EToken.PAREN_T.getState(), EParen.CLOSE.getState()))
                        {
                                // a no-parameter function
                                return _appInterface.FinishFunction(matchWrapper);
                        }
                        else if (ParseParameters(matchWrapper,flags) == EParseResult.kMatch)
                        {
                                if (Lexer().IsToken(EToken.PAREN_T.getState(), EParen.CLOSE.getState()))
                                {
                                        return _appInterface.FinishFunction(matchWrapper);
                                }
                                else
                                {
                                        match = _appInterface.CreateErrorNode("Function " + funcName + " missing closing parenthesis.");
                                         matchWrapper.SetObjectRef(match);
                                        return EParseResult.kBadExpression;
                                }
                        }
                }

                // didn't match function, so replace the identifier
               try{
                 Lexer().PushbackToken();
               }catch(SB_Exception e){

               }
        }
        matchWrapper.SetObjectRef(match);
        return (match == null) ? EParseResult.kNoMatch : EParseResult.kBadExpression;
    }

      
    private EParseResult ParseParameters(SB_ObjectRefWrapper matchWrapper, EParseFlags flags)
    throws SB_ParseException
    {
        //FATAL( (match != null), "Error in ParseParameters" );

        SB_ExpressionNode param = null;
        SB_ObjectRefWrapper paramWrapper = new SB_ObjectRefWrapper(param);
        if (ParseExpression(paramWrapper,flags) == EParseResult.kNoMatch)
        {
                // already checked for no-parameter function earlier, so this is a syntax error
                param = _appInterface.CreateErrorNode("Syntax error in function parameter.");
        }else{
          param = (SB_ExpressionNode)paramWrapper.GetObjectRef();
        }
        SB_ExpressionNode match = (SB_ExpressionNode)matchWrapper.GetObjectRef();
        // found a parameter
        _appInterface.AddArgument( match, param );
         matchWrapper.SetObjectRef(match);
        return ParseParametersAux(matchWrapper,flags);
     }

     private EParseResult ParseParametersAux(SB_ObjectRefWrapper matchWrapper, EParseFlags flags)
     throws SB_ParseException
     {
        //FATAL( (match != null), "Error in ParseParametersAux" );
        SB_ExpressionNode match = (SB_ExpressionNode)matchWrapper.GetObjectRef();
        if (Lexer().IsToken(EToken.COMMA_T.getState()))
        {
                // found comma separator

                EParseResult result = ParseParameters(matchWrapper,flags);
                if (result == EParseResult.kNoMatch)
                {
                        match = _appInterface.CreateErrorNode("Expected function parameter after comma.");
                         matchWrapper.SetObjectRef(match);
                        return EParseResult.kBadExpression;
                }
                else
                {
                        return result;
                }
        }
        else
        {
                return EParseResult.kMatch;	// EMPTY PRODUCTION
        }
      }

      private EParseResult ParseVector(SB_ObjectRefWrapper matchWrapper)
      {
        double[] x = new double[]{0.0};
        double[] y = new double[]{0.0};
        double[] z = new double[]{0.0};
        SB_ExpressionNode match = (SB_ExpressionNode)matchWrapper.GetObjectRef();
        // square brackets around vector constants are MANDATORY
        if (Lexer().IsToken(EToken.BRACKET_T.getState(), EParen.OPEN.getState()))
        {
                if (ParseNumber(x))
                {
                        // eat optional comma
                        Lexer().IsToken(EToken.COMMA_T.getState());

                        if (ParseNumber(y))
                        {
                                // eat optional comma
                                Lexer().IsToken(EToken.COMMA_T.getState());

                                if (ParseNumber(z))
                                {
                                        // check for closing bracket
                                        if (Lexer().IsToken(EToken.BRACKET_T.getState(),EParen.CLOSE.getState()))
                                        {
                                                match = _appInterface.CreateConstantNode(x[0],y[0],z[0]);
                                                 matchWrapper.SetObjectRef(match);
                                                return EParseResult.kMatch;
                                        }
                                        else
                                        {
                                                match = _appInterface.CreateErrorNode("Expected closing bracket of vector constant, got " +  Lexer().GetCurrentToken().lex_str + " instead.");
                                                matchWrapper.SetObjectRef(match);
                                                return EParseResult.kBadExpression;
                                        }
                                }
                                else
                                {
                                        match = _appInterface.CreateErrorNode("Expected third element of vector constant, got " +  Lexer().GetCurrentToken().lex_str + " instead.");
                                         matchWrapper.SetObjectRef(match);
                                        return EParseResult.kBadExpression;
                                }
                        }
                        else
                        {
                                match = _appInterface.CreateErrorNode("Expected second element of vector constant, got " + Lexer().GetCurrentToken().lex_str + " instead.");
                                 matchWrapper.SetObjectRef(match);
                                return EParseResult.kBadExpression;
                        }
                }
                else
                {
                        match = _appInterface.CreateErrorNode("Expected first element of vector constant, got " + Lexer().GetCurrentToken().lex_str + " instead.");
                        matchWrapper.SetObjectRef(match);
                        return EParseResult.kBadExpression;
                }
        }

        return EParseResult.kNoMatch;
      }

      private EParseResult ParseArray(SB_ObjectRefWrapper matchWrapper)
      {
        SB_ExpressionNode match = (SB_ExpressionNode)matchWrapper.GetObjectRef();

        String str = new String(Lexer().GetCurrentToken().lex_str);

		if (Lexer().IsToken(EToken.CURLYBRACE_T.getState(),EParen.OPEN.getState()))
		{
			ArrayList arrayptr = new ArrayList();
            boolean justAteComma = false;
	
	          while(!Lexer().IsToken(EToken.CURLYBRACE_T.getState(),EParen.CLOSE.getState()))
	          {
	            //If the next token is a comma then we are looking at an empty entry
	            if( Lexer().IsToken(EToken.COMMA_T.getState(), SB_Lexer.ANY_SUBTYPE ))
	            {
	              arrayptr.add(_appInterface.CreateConstantNode(""));
                  justAteComma = true;
	            }
	            else
	            {
	              SB_ExpressionNode exp = null;
	              SB_ObjectRefWrapper expWrapper = new SB_ObjectRefWrapper(exp);
	              try
	              {
	                EParseResult result = ParseExpression( expWrapper, EParseFlags.kNoFlag );
	                if( EParseResult.kMatch == result )
	                {
                      // found a non-empty array element
	                  arrayptr.add( expWrapper.GetObjectRef() );
                      
                      // consume the comma if it is present
	                  justAteComma = Lexer().IsToken(EToken.COMMA_T.getState()); 
	                }
	                else
	                  return result;
	
	              }
	              catch (SB_ParseException exc)
	              {
	                // politely return an error
	                match = _appInterface.CreateErrorNode(exc.getMessage());
	              }
	            }
	          }
	
              if (justAteComma)
              {
                  arrayptr.add(_appInterface.CreateConstantNode(""));
              }
              
	          //At this poit we have an array of strings
	          match = _appInterface.CreateArrayNode(arrayptr);
	          matchWrapper.SetObjectRef(match);
	
	          return EParseResult.kMatch;
		}
	
		return EParseResult.kNoMatch;
      }

      private boolean ParseNumber(double[] number)
      {
        // extract either a positive or negative number constant
        if (Lexer().IsToken(EToken.INTCON_T.getState()) ||
                Lexer().IsToken(EToken.REALCON_T.getState()))
        {
                number[0] = Double.parseDouble(Lexer().GetPreviousToken().lex_str);
                return true;
        }
        else if (Lexer().IsToken(EToken.ADDOP_T.getState(),EAddop.SUB.getState()))
        {
                // find the number that goes with the negative sign
                if (Lexer().IsToken(EToken.INTCON_T.getState()) ||
                        Lexer().IsToken(EToken.REALCON_T.getState()))
                {
                        number[0] = - Double.parseDouble(Lexer().GetPreviousToken().lex_str);
                        return true;
                }
        }

        return false;
      }

      private EBinaryOp MapBinaryOperator(lexeme token) {
        if(token.type == EToken.AND_T.getState())
          return EBinaryOp.kAndOp;
        else if(token.type == EToken.OR_T.getState())
          return EBinaryOp.kOrOp;
        else if(token.type == EToken.DOT_T.getState())
          return EBinaryOp.kDotOp;
        else if(token.type == EToken.ADDOP_T.getState()){
                if (token.subtype == EAddop.ADD.getState())
                  return EBinaryOp.kAddOp;
                else if(token.subtype == EAddop.SUB.getState())
                  return EBinaryOp.kSubOp;
                else
                  return null; //error
                }
        else if(token.type == EToken.MULOP_T.getState()){
                if(token.subtype == EMulop.MULT.getState())
                  return EBinaryOp.kMultOp;
                else if(token.subtype == EMulop.DIV.getState())
                  return EBinaryOp.kDivOp;
                else if(token.subtype == EMulop.MOD.getState())
                  return EBinaryOp.kModOp;
                else return null; //error
                }
        else if(token.type == EToken.RELOP_T.getState()){
                if (token.subtype == ERelop.LEQ.getState())
                  return EBinaryOp.kLeqOp;
                else if(token.subtype == ERelop.LSS.getState())
                  return EBinaryOp.kLssOp;
                else if(token.subtype == ERelop.GEQ.getState())
                  return EBinaryOp.kGeqOp;
                else if(token.subtype == ERelop.GRT.getState())
                  return EBinaryOp.kGrtOp;
                else if(token.subtype == ERelop.NEQ.getState())
                  return EBinaryOp.kNeqOp;
                else if(token.subtype == ERelop.EQL.getState())
                  return EBinaryOp.kEqlOp;
                else return null; //error
                }

        return null;	// error
   }

   public static String BinaryOpToString(EBinaryOp op)
   {
        if(op == EBinaryOp.kAndOp)
          return "&&";
        else if(op == EBinaryOp.kOrOp)
          return "||";
        else if(op == EBinaryOp.kAddOp)
          return "+";
        else if(op == EBinaryOp.kSubOp)
          return "-";
        else if(op == EBinaryOp.kMultOp)
          return "*";
        else if(op == EBinaryOp.kDivOp)
          return "/";
        else if(op == EBinaryOp.kModOp)
          return "%";
        else if(op == EBinaryOp.kLeqOp)
          return "<=";
        else if(op == EBinaryOp.kLssOp)
          return "<";
        else if(op == EBinaryOp.kGeqOp)
          return ">=";
        else if(op == EBinaryOp.kGrtOp)
          return ">";
        else if(op == EBinaryOp.kNeqOp)
          return "!=";
        else if(op == EBinaryOp.kEqlOp)
          return "==";
        else return "(unknown operator)";
   }


   private EUnaryOp MapUnaryOperator(lexeme token) {
        if ((token.type == EToken.ADDOP_T.getState()) &&
                (token.subtype == EAddop.SUB.getState())) {
                return EUnaryOp.kNegateOp;
        }
        else if (token.type == EToken.BANG_T.getState()) {
                return EUnaryOp.kNotOp;
        }

        return null; // error
    }

    private String UnaryOpToString(EUnaryOp op)
    {
        if(op == EUnaryOp.kNegateOp)
          return "-";
        else if(op == EUnaryOp.kNotOp)
          return "!";
        else return "(unknown operator)";
    }
}